<template>
  <!-- 考试模式 -->
  <div class="sbodyd">
    <div class="mainboxgj">
      <!-- 分2 -->
      <div class="mainboxleft">
        <div class="mainlefttopbox">
          <div class="mainsera">
            <div class="xbannername" @click="goback"> <icon-left /> 返回 </div>
            <div class="timerbox">倒计时:{{ formattedTimes }}</div>

            <div class="startbox" @click="waivefn" v-if="startshow"
              >放弃考核</div
            >
            <div class="startbox" @click="choicefn" v-if="startshow"
              >切换试题</div
            >
            <div class="startbox" @click="saveKhfn">交卷</div>
          </div>
          <div class="maintoptitle">{{ partsName }}</div>
          <div class="maintopright">
            <div class="czmainitem tool" @click="zoomIn">
              <img src="@/assets/images/fd.png" alt="" class="normal" />
              <img src="@/assets/images/fdac.png" alt="" class="active" />
            </div>
            <div class="czmainitem tool" @click="zoomOut">
              <img src="@/assets/images/sx.png" alt="" class="normal" />
              <img src="@/assets/images/sxac.png" alt="" class="active" />
            </div>
            <div class="czmainitem tool" @click="tdflag = true">
              <img src="@/assets/images/td.png" alt="" class="normal" />
              <img src="@/assets/images/tdac.png" alt="" class="active" />
            </div>
          </div>
        </div>

        <div class="box" ref="boxd">
          <canvas id="myCanvaslxd" :width="hbwidth" :height="hbheight"></canvas>
        </div>
        <div class="lbox" ref="gosroll">
          <div
            v-for="(item, index) in imgsrc"
            :key="index"
            class="lboxitem"
            @click="tagdcom(item.medicineAtlasImgId)"
          >
            <img :src="`${base + item.imgUrl}`" />
            <div class="msx" v-if="item.medicineAtlasImgId == dcomid"></div>
          </div>
        </div>
      </div>
      <!-- 分右边 -->

      <div class="bocd">
        <div class="gnbocdtop">
          <div class="xugn">
            <div class="xugname">解剖面：</div>
            <a-select
              @change="changeimgclassfn"
              v-model="classificationName"
              :options="imgclassdata"
              :field-names="fieldNames"
              :style="{ width: '250px' }"
              placeholder="请选择解剖面"
            />
          </div>
          <div class="xugn" v-if="imggroup.length > 0">
            <div class="xugname">图像组：</div>
            <a-select
              @change="changeimggroupfn"
              v-model="imggroupname"
              :options="imggroup"
              :field-names="fieldNamess"
              :style="{ width: '250px' }"
              placeholder="请选择图像分组"
            />
          </div>
        </div>
        <div class="gnbocd">
          <div class="gnbocdname">解剖部位</div>
          <div class="gnboxmain">
            <div class="gnboxitem jgdovx" v-if="optionsdata.length > 0">
              所有
              <a-switch v-model="allflag" @change="changecsd()" />
            </div>
            <div v-for="(item, index) in optionsdata" :key="index">
              <div ref="cs" class="jgdovx gnboxitem" v-if="flagfn(item)">
                {{ item.anatomicStructureName }}
                <a-switch v-model="item.flag" @change="changecs(item)" />
              </div>
            </div>
          </div>
        </div>
        <div class="gnbottom">
          <div class="tool" @click="tagdcoms('-1')">
            <img src="@/assets/images/letac.png" alt="" class="normal" />
            <img src="@/assets/images/let.png" alt="" class="active" />
          </div>
          <div class="mentox"
            >影像页数:<span>{{ findindex() + 1 }}/{{ imgsrc.length }}</span>
          </div>
          <div class="tool" @click="tagdcoms('1')">
            <img src="@/assets/images/rght.png" alt="" class="normal" />
            <img src="@/assets/images/rghtac.png" alt="" class="active" />
          </div>
        </div>
      </div>
    </div>
    <!-- 弹出填写试题答案的选择框 -->
    <a-modal
      v-model:visible="visible"
      @cancel="handleCancel"
      :on-before-ok="handleBeforeOk"
      unmountOnClose
    >
      <template #title> 填写 </template>
      <div>
        <a-form :model="formModel">
          <a-form-item field="userText" label="答案">
            <a-input
              v-model="formModel.userText"
              placeholder="请输入答案"
              allow-clear
            />
          </a-form-item>
        </a-form>
      </div>
    </a-modal>
    <!-- 选择考核试题 -->
    <div class="tcbox" v-if="ksshow">
      <div class="tctopbox">
        <div class="tctopname">考核详细信息</div>
        <div class="tcclose" @click="ksshow = false"
          ><icon-close :size="25"
        /></div>
      </div>
      <div class="tcmainbox">
        <div class="tcmainitem">
          <!-- {{khitem}} -->
          <div class="tcitemname">考核名称</div>
          <div class="tcitdes">{{ khitem.examineName }}</div>
        </div>
        <div class="tcmainitem">
          <div class="tcitemname">组织教师</div>
          <div class="tcitdes">{{ khitem.examineName }}</div>
        </div>
        <div class="tcmainitem">
          <div class="tcitemname">时限</div>
          <div class="tcitdes">{{ khitem.examineTime }}分钟</div>
        </div>
        <div class="tcmainitem">
          <div class="tcitemname">时间</div>
          <div class="tcitdes"
            >{{ khitem.startTime }} ~ {{ khitem.endTime }}</div
          >
        </div>
        <div class="tcmainitem">
          <div class="tcitemname">选择图谱</div>
          <div class="tcitdes">
            <a-select
              :options="optionsdata"
              placeholder="请选择图谱"
              :field-names="{
                value: 'medicineAtlasId',
                label: 'medicineAtlasName',
              }"
              :style="{ width: '100%', height: '100%' }"
              @change="changefn"
              v-model="medicineAtlasId"
            />
          </div>
        </div>
      </div>
      <div class="tsred" v-if="tipshow">请先选择图谱才能进行作答</div>
      <div class="startboxss" @click="gostart">开始作答</div>
    </div>
    <div class="zzcbox" v-if="ksshow"></div>
    <!-- 放弃考核提示 -->
    <a-modal
      width="auto"
      v-model:visible="visibletipshow"
      @ok="handleOktips"
      @cancel="handleCanceltips"
    >
      <template #title> 提示 </template>
      <div>{{ visibletip }}</div>
    </a-modal>
    <!-- 加载页 -->
    <div class="loader-container" v-if="loding">
      <div class="loader"></div>
      <p class="pd">加载中90%</p>
    </div>
  </div>
</template>

<script lang="ts" setup>
  import {
    defineComponent,
    reactive,
    ref,
    onUnmounted,
    onMounted,
    onBeforeUnmount,
  } from 'vue';
  import { Message, Modal } from '@arco-design/web-vue';
  import { getPoint, jpList, getPointnew } from '@/api/tplist.ts';
  import {
    getTp,
    getTplist,
    waive,
    getInput,
    saveKh,
    lssava,
  } from '@/api/examine.ts';

  import { useRoute } from 'vue-router';
  import { useRouter } from 'vue-router';
  const router = useRouter();
  // 获取路由信息
  const route = useRoute();
  // 放弃考核提示
  const visibletipshow = ref(false);
  // 加载动画
  const loding = ref(false);
  const visibletip = ref('');
  const handleOktips = () => {
    if (visibletip.value == '确定放弃考试吗？确认后提交成绩！') {
      waive({
        examineRecordId: examineRecordId.value,
        studentId: studentId.value,
        medicineAtlasId: medicineAtlasId.value,
      }).then((res) => {
        if (res.code == 200) {
          //
          console.log('放弃考核成功', res.data);
          router.push({
            name: 'exramlist',
          });
        }
      });
    }

    if (visibletip.value == '确认交卷吗?') {
      saveKh(examineRecordDetailsListdata.value).then((res) => {
        if (res.code == 200) {
          console.log('交卷成功');
          router.push({
            name: 'exramlist',
          });
        }
      });
    }
    if (visibletip.value == '考试结束,请点击确定提交考试！') {
      saveKh(examineRecordDetailsListdata.value).then((res) => {
        if (res.code == 200) {
          console.log('交卷成功');
          router.push({
            name: 'exramlist',
          });
        }
      });
    }
  };
  const handleCanceltips = () => {
    visibletip.value = '';
    if (visibletip.value == '考试结束,请点击确定提交考试！') {
      saveKh(examineRecordDetailsListdata.value).then((res) => {
        if (res.code == 200) {
          console.log('交卷成功');
          router.push({
            name: 'exramlist',
          });
        }
      });
    }
  };
  // 获取查询参数
  //考核完成
  // console.log('获取到考核id', route.params, route, route.params);
  const examineId = ref(route.query.examineId); // 确保类型安全
  const studentId = ref(route.query.studentId);
  const examineRecordId = ref(route.query.examineRecordId);
  // const examineTime = ref(route.query.examineTime);
  const medicineAtlasId = ref(Number(route.query.medicineAtlasId));
  const khitem = ref(JSON.parse(route.query.khitem));
  const tipshow = ref(false);
  // 选择考试
  const ksshow = ref(false);

  // console.log('获取到考核id', examineRecordId.value, khitem.value);
  // s图谱id
  // const medicineAtlasId = ref('');
  // 考核相关代码开始
  // 切换考核试题
  const choicefn = () => {
    ksshow.value = true;
    // khitem.value = item
    // examineId.value = item.examineId;
    // examineTime.value = item.examineTime;
    getTp({
      examineId: examineId.value,
    }).then((res) => {
      if (res.code == 200) {
        console.log('查询考核图谱列表成功', res.data);
        optionsdata.value = res.data;
      }
    });
  };
  const changefn = () => {
    tipshow.value = false;
    console.log('当前选择的考核图谱id', medicineAtlasId.value);
  };
  // 切换试题重新渲染并且操作
  const gostart = () => {
    if (medicineAtlasId.value) {
      let type = '';
      let imgClassification = '';
      optionsdata.value.forEach((item) => {
        if (item.medicineAtlasId == medicineAtlasId.value) {
          // console.log('查询到相同',item);
          type = item.type;
          imgClassification = item.imgClassificationStr;
        }
      });
      getTplist({
        medicineAtlasId: medicineAtlasId.value,
        type: type,
        imgClassification: imgClassification,
      }).then((ress) => {
        if (ress.code == 200) {
          // console.log('查询考核图谱列表成功', ress.data);
          imgsrc.value = ress.data.allImg;
          imgsrcs.value = ress.data.allImg;
          imgclassdata.value = ress.data.classification;
          dcomid.value = ress.data.allImg[0].medicineAtlasImgId;
          state.img.src = base.value + imgsrc.value[0].imgUrl;
          draw('');
          ksshow.value = false;
          // 设置存储图谱的考核题目数据
          const flag = examineRecordDetailsListdata.value.find(
            (item) => item.medicineAtlasId == medicineAtlasId.value
          );
          // console.log('查询是否有新的图谱',flag,medicineAtlasId.value,examineRecordDetailsListdata.value);

          if (!flag) {
            examineRecordDetailsListdata.value.push({
              examineRecordId: examineRecordId.value,
              studentId: studentId.value,
              examineId: examineId.value,
              medicineAtlasId: medicineAtlasId.value,
              examineRecordDetailsList: [],
            });
          } else {
            console.log('已存在考核了');
          }

          // 查询标记点为
          getPointfn();
        }
      });
    } else {
      tipshow.value = true;
    }
  };
  // 倒计时

  // // 调用示例
  // startCountdown(5); // 从5分钟开始倒计时

  // 倒计时样式
  const formattedTimes = ref('');
  const formatTime = (seconds) => {
    const mins = Math.floor(seconds / 60);
    const secs = seconds % 60;

    if (seconds === 0) {
      visibletip.value = '考试结束,请点击确定提交考试！';
      visibletipshow.value = true;
    }

    return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
  };

  // 倒计时执行函数
  const startCountdown = (endTime) => {
    const endDate = new Date(endTime).getTime();
    const interval = setInterval(() => {
      const now = Date.now();
      const remainingTimeInSeconds = Math.max((endDate - now) / 1000, 0);
      const formattedTime = formatTime(Math.floor(remainingTimeInSeconds));

      formattedTimes.value = formattedTime;

      if (remainingTimeInSeconds <= 0) {
        clearInterval(interval);
        visibletip.value = '考试结束,请点击确定提交考试！';
        visibletipshow.value = true;
      }
    }, 1000);
  };

  startCountdown(khitem.value.endTime);

  // 设置考核空题库

  // 先查询图谱
  // 查询返回的图谱详细 需要解剖面和 类型

  // 定义当前考试图谱id

  // 考核数据
  const examineRecordDetailsList = ref([]);
  // 多图谱考核数据
  const examineRecordDetailsListdata = ref([]);
  // 放弃考核
  const waivefn = () => {
    visibletipshow.value = true;
    visibletip.value = '确定放弃考试吗？确认后提交成绩！';
  };
  // 获取考核意外退出的临时保存信息
  const getinputfn = () => {
    getInput({
      examineRecordId: examineRecordId.value,
      studentId: studentId.value,
      medicineAtlasId: medicineAtlasId.value,
    }).then((res) => {
      if (res.code == 200) {
        examineRecordDetailsList.value = res.data;

        examineRecordDetailsList.value.forEach((item) => {
          // 获取完记录映射到 画布中需要
          state.markers.forEach((itemd) => {
            itemd.bsdata.forEach((items) => {
              if (items.markingPointsId == item.markingPointsId) {
                items.userText = item.pointNameInput;
              }
            });
          });
        });
        //  把缓存存入
        examineRecordDetailsListdata.value.forEach((item) => {
          if (item.medicineAtlasId == medicineAtlasId.value) {
            item.examineRecordDetailsList = examineRecordDetailsList.value;
          }
        });
        saveMarkers();
        draw('');
      }
    });
  };

  // 交卷
  const saveKhfn = () => {
    visibletip.value = '确认交卷吗?';
    visibletipshow.value = true;
  };
  const lssavafn = () => {
    lssava({
      examineRecordId: examineRecordId.value,
      studentId: studentId.value,
      examineId: examineId.value,
      medicineAtlasId: medicineAtlasId.value,
      examineRecordDetailsList: examineRecordDetailsList.value,
    }).then((res) => {
      if (res.code == 200) {
        console.log('临时交卷成功');
      }
    });
  };
  // 隔一分钟提交一次 接口 用来临时存储答题数据
  // 每隔一分钟提交一次
  const intervalId = setInterval(lssavafn, 60 * 1000);

  // 清理定时器的函数（可根据需要调用）
  const stopSaving = () => {
    clearInterval(intervalId);
  };
  // 考核相关代码结束

  interface Marker {
    x: number;
    y: number;
    color: string;
    text?: string;
  }

  // const emit = defineEmits<{
  //   (event: 'customEvent', payload: any): void; // 定义自定义事件
  // }>();

  // 模糊搜索本地
  // const inputser = (e) => {
  //   state.markers.forEach((item) => {
  //     if (
  //       item.medicineAtlasImgId.split(',').map(Number).includes(dcomid.value)
  //     ) {
  //       item.bsdata.forEach((items) => {
  //         if (items.text == e) {
  //           state.hoveredMarker = items;
  //           draw("");
  //           console.log('触发了模糊搜索', state.hoveredMarker);
  //         }
  //       });
  //     }
  //   });
  // };

  const imgsrc = ref([]);
  const imgsrcs = ref([]);
  const imggroup = ref('');
  const imgclassdata = ref('');
  const partsName = ref('');

  const base = ref(window.config.VUE_APP_IMG_API);
  // console.log('Win', imgclassdata.value, imggroup.value);
  // const medicineAtlasId = ref(props.medicineAtlasId);
  // console.log('接收到', imgsrc.value, base.value);
  const state = reactive({
    showText: false,
    canBiaoZhu: false,
    pointColor: '#65FF00',
    pointSize: 7,
    imgScale: 1,
    zoomStep: 0.1,
    markers: [] as { dcomid: number; bsdata: Marker[] }[],
    canvas: null as HTMLCanvasElement | null,
    ctx: null as CanvasRenderingContext2D | null,
    img: new Image(),
    // imgWidth: 1300,
    // imgHeight: 500,
    imgWidth: 480,
    imgHeight: 606,
    currentText: '',
    currentMarker: null as Marker | null,
    showLinesAndText: true,
    isDragging: false,
    startDragX: 0,
    startDragY: 0,
    imgOffsetX: 0,
    imgOffsetY: 0,
    isSpacePressed: false,
    hoveredMarker: null as Marker | null,
    editingMarker: false,
    editPanelX: 0,
    editPanelY: 0,
    addflag: false,
    flipHorizontal: false,
    flipVertical: false,
    rotation: 0, // 0, 90, -90
  });
  const markingPointsId = ref('');
  const dcomid = ref(1);
  const goback = () => {
    console.log('执行了关闭');

    // emit('goback');
    router.push({
      name: 'exramlist',
    });
  };
  const flipHorizontald = () => {
    state.flipHorizontal = !state.flipHorizontal;
    draw('');
  };

  const flipVerticald = () => {
    state.flipVertical = !state.flipVertical;
    draw('');
  };

  const rotate90 = () => {
    state.rotation = (state.rotation + 90) % 360;
    draw('');
  };

  const rotateMinus90 = () => {
    state.rotation = (state.rotation - 90 + 360) % 360;
    draw('');
  };

  const checkHover = (x: number, y: number) => {
    // 从状态中解构出相关的属性
    const { markers, pointSize, imgScale, imgOffsetX, imgOffsetY } = state;
    const margin = 150; // 离画布边缘的距离

    // 根据 dcomid 查找当前的标记元素
    // const targetElement = markers.find(
    //   (item) => item.dcomid === dcomid.value
    // );
    // const targetElement = markers.find((item) =>
    //   item.medicineAtlasImgId.includes(dcomid.value)
    // );
    const mergedBsdata = markers.filter((item: any) =>
      item.medicineAtlasImgId.includes(dcomid.value)
    );
    // 合并 bsdata
    const targetElement = { bsdata: [] as Marker[] };

    targetElement.bsdata = mergedBsdata.flatMap((item) => item.bsdata);
    // console.log('查找当前标记元素', targetElement);

    if (targetElement) {
      // 找到目标标记元素中的标记
      for (let marker of targetElement.bsdata) {
        // 获取画布和上下文
        const canvas = state.canvas!;
        const ctx = state.ctx!;

        // 计算缩放后的图像尺寸
        const scaledWidth = state.imgWidth * state.imgScale;
        const scaledHeight = state.imgHeight * state.imgScale;

        // 计算图像在画布上的偏移量
        const xOffset = (canvas.width - scaledWidth) / 2 + state.imgOffsetX;
        const yOffset = (canvas.height - scaledHeight) / 2 + state.imgOffsetY;

        // 计算标记的位置
        const markerX = marker.x * state.imgScale + xOffset;
        const markerY = marker.y * state.imgScale + yOffset;

        // 检查是否悬停在标记点上
        if (
          Math.hypot(x - markerX, y - markerY) <
          (pointSize / 2) * imgScale * 3
        ) {
          state.hoveredMarker = marker;
          // console.log('悬停在标记点', state.hoveredMarker);
          return true;
        }

        // 检查是否悬停在文本上
        const text = marker.text || '';
        ctx.font = `12px Arial`; // 根据实际使用的字体进行设置
        const textMetrics = ctx.measureText(text);
        const textWidth = textMetrics.width;

        // 使用 marker.textX 和 marker.textY
        const textX = marker.textX;
        const textY = marker.textY;

        const textHeight = 14 * imgScale;

        // 计算文本的边界框
        const textBoundingBox = {
          left: textX - textWidth, // 左边界
          right: textX + textWidth, // 右边界
          top: textY - textHeight, // 上边界
          bottom: textY, // 下边界
        };

        if (
          x >= textBoundingBox.left &&
          x <= textBoundingBox.right &&
          y >= textBoundingBox.top &&
          y <= textBoundingBox.bottom
        ) {
          state.hoveredMarker = marker;
          // console.log('悬停在文本上', x, textBoundingBox.left);
          return true;
        }
      }
    }

    // 没有悬停在任何标记、线段或文本上
    state.hoveredMarker = null;
    // console.log('移动', state.hoveredMarker);
    return false;
  };

  const handleMouseMove = (e: MouseEvent | TouchEvent) => {
    // console.log('触摸事件');

    // 判断是否为触摸事件
    const isTouchEvent = (e: MouseEvent | TouchEvent): e is TouchEvent =>
      'touches' in e;

    let canvasX: number, canvasY: number;

    if (isTouchEvent(e)) {
      // 获取触摸事件的坐标
      const touch = e.touches[0];
      const rect = state.canvas!.getBoundingClientRect();
      canvasX = touch.clientX - rect.left;
      canvasY = touch.clientY - rect.top;
    } else {
      // 获取鼠标事件的坐标
      canvasX = e.offsetX;
      canvasY = e.offsetY;
    }
    if (state.isDragging) {
      dragMove(e);
    } else {
      checkHover(canvasX, canvasY);
      draw('');
    }
    // console.log('移动了', e);
  };

  const handleCanvasClick = (e: MouseEvent | TouchEvent) => {
    // console.log('当前是查询点击');

    let canvasX: number, canvasY: number;

    if ('touches' in e) {
      // 触摸事件
      const touch = e.touches[0];
      const rect = state.canvas!.getBoundingClientRect();
      canvasX = touch.clientX - rect.left;
      canvasY = touch.clientY - rect.top;
      checkHover(canvasX, canvasY);
      // 只有在需要阻止默认行为时调用
      e.preventDefault();
    } else {
      // 鼠标事件
      canvasX = e.offsetX;
      canvasY = e.offsetY;
    }
    if (state.canBiaoZhu) {
      const canvasX = e.offsetX;
      const canvasY = e.offsetY;
      const imgX =
        (canvasX -
          (state.canvas!.width / 2 - (state.imgWidth * state.imgScale) / 2)) /
        state.imgScale;
      const imgY =
        (canvasY -
          (state.canvas!.height / 2 - (state.imgHeight * state.imgScale) / 2)) /
        state.imgScale;
      createMarker(imgX, imgY);
    } else if (state.hoveredMarker) {
      state.currentMarker = state.hoveredMarker;
      state.currentText = state.currentMarker.text || '';
      markingPointsId.value = state.currentMarker.markingPointsId;
      // 正在考试
      handleClick();
    }
  };

  const createMarker = (x: number, y: number) => {
    if (state.canBiaoZhu) {
      state.addflag = true;
      state.currentMarker = { x, y, color: state.pointColor };
      draw('');
    }
  };

  const zoomIn = () => {
    state.imgScale += state.zoomStep;
    draw('');
  };

  const zoomOut = () => {
    if (state.imgScale > state.zoomStep) {
      state.imgScale -= state.zoomStep;
      draw('');
    }
  };
  const leftMarkers = ref([]);
  const rightMarkers = ref([]);

  const draw = (mbmarker: any) => {
    console.log('当前缩放比例', state.imgScale);

    // console.log('来自哪里的重绘', mbmarker);

    const canvas = state.canvas!;
    const ctx = state.ctx!;
    const img = state.img;

    if (state.imgWidth == 0) {
      return;
    }

    // 清空画布
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    const scaledWidth = state.img.naturalWidth * state.imgScale;
    const scaledHeight = state.img.naturalHeight * state.imgScale;

    // 计算图像在画布上的偏移
    const xOffset = (canvas.width - scaledWidth) / 2 + state.imgOffsetX;
    const yOffset = (canvas.height - scaledHeight) / 2 + state.imgOffsetY;

    ctx.save();

    // 应用变换
    ctx.translate(canvas.width / 2, canvas.height / 2); // 移动到画布中心
    if (state.flipHorizontal) ctx.scale(-1, 1); // 水平翻转
    if (state.flipVertical) ctx.scale(1, -1); // 垂直翻转
    ctx.rotate((state.rotation * Math.PI) / 180); // 旋转
    ctx.translate(-canvas.width / 2, -canvas.height / 2); // 回到原位置

    // 绘制图像
    ctx.drawImage(img, xOffset, yOffset, scaledWidth, scaledHeight);

    // 恢复上下文状态为绘制标记做准备
    ctx.restore();
    ctx.save();

    // 重新应用变换
    ctx.translate(canvas.width / 2, canvas.height / 2);
    if (state.flipHorizontal) ctx.scale(-1, 1);
    if (state.flipVertical) ctx.scale(1, -1);
    ctx.rotate((state.rotation * Math.PI) / 180);
    ctx.translate(-canvas.width / 2, -canvas.height / 2);

    const margin = 170; // 从画布边缘的边距
    const textHeight = 12; // 文本高度
    const verticalSpacing = 5; // 文本之间的垂直间隔
    const textMargin = 20; // 文本与边缘的距离

    // 记录所有标记的位置和文本
    leftMarkers.value = [];
    rightMarkers.value = [];

    // 定义绘制标记和文本的函数
    const drawMarkersAndText = (markers: any[], isLeft: boolean) => {
      // console.log('继续执行');
      markers.forEach((item) => {
        const itemsArray = item.medicineAtlasImgId.split(',').map(Number);

        if (itemsArray.includes(dcomid.value)) {
          item.bsdata.forEach((marker: any) => {
            const markerX = marker.x * state.imgScale + xOffset;
            const markerY = marker.y * state.imgScale + yOffset;

            // 划分左右位置数组保存
            const count = leftMarkers.value.filter(
              (item: any) => item.flag == true
            ).length;
            const counts = rightMarkers.value.filter(
              (item: any) => item.flag == true
            ).length;

            // 根据位置将标记存入对应数组
            if (isLeft) {
              if (markerX < canvas.width / 2) {
                if (count > 23) {
                  leftMarkers.value.push(marker);
                } else {
                  marker.lintextshow = marker.flag;
                  leftMarkers.value.push(marker);
                }
              }
            } else {
              if (markerX >= canvas.width / 2) {
                if (counts > 23) {
                  marker.lintextshow = false;
                  rightMarkers.value.push(marker);
                } else {
                  marker.lintextshow = marker.flag;
                  rightMarkers.value.push(marker);
                }
              }
            }

            // 绘制标记点
            if (marker.flag) {
              ctx.fillStyle =
                marker == state.hoveredMarker ? '#409EFF' : '#' + marker.color;
              if (mbmarker == '搜索') {
                ctx.fillStyle =
                  marker == state.hoveredMarker
                    ? 'rgba(255, 0, 0, 1)'
                    : 'rgba(128, 128, 128, 0.5)';
              }
              ctx.beginPath();
              ctx.arc(markerX, markerY, state.pointSize / 2, 0, 2 * Math.PI);
              ctx.fill();
            }
          });
        }
      });
    };

    // 绘制左侧和右侧的标记
    drawMarkersAndText(state.markers, true); // 左侧标记
    drawMarkersAndText(state.markers, false); // 右侧标记

    // 左右数组优化调整顺序
    leftMarkers.value.sort((a: any, b: any) => a.y - b.y);
    rightMarkers.value.sort((a: any, b: any) => a.y - b.y);

    // 计算可用的文本区域
    const totalTextHeight =
      leftMarkers.value.length * (textHeight + verticalSpacing) -
      verticalSpacing; // 总共文本高度
    const availableHeight = canvas.height - 2 * textMargin;
    const startY = Math.max(
      textMargin,
      (availableHeight - totalTextHeight) / 2 + textMargin
    );

    // 计算每个文本的纵向位置并存放位置
    const calculateTextPositions = (markers: any, isLeft: any) => {
      let yPosition = startY;
      markers.forEach((marker: any) => {
        if (marker.flag && marker.lintextshow) {
          if (yPosition > 750 - 2 * textHeight) {
            // 超出最大高度
            marker.lintextshow = marker == mbmarker;
            if (marker.lintextshow) {
              marker.textY = leftMarkers.value[0].textY; // 显示文本
            }
          } else {
            marker.textY = yPosition;
            marker.lintextshow = true;
            yPosition += textHeight + verticalSpacing;
          }
        }
      });
    };

    // 计算左侧和右侧文本位置
    calculateTextPositions(leftMarkers.value, true);
    calculateTextPositions(rightMarkers.value, false);

    // 定义绘制文本和线条的函数
    const drawTextAndLines = (markers: any, isLeft: any) => {
      markers.forEach((marker: any, index) => {
        const { text, textY } = marker;
        const markerX = marker.x * state.imgScale + xOffset;
        const markerY = marker.y * state.imgScale + yOffset;
        const textX = isLeft ? margin : canvas.width - margin;
        // console.log('是谁', marker.lintextshow, marker.flag, marker.labels);

        if (marker.lintextshow && marker.flag && marker.labels) {
          ctx.strokeStyle =
            marker == state.hoveredMarker ? '#409EFF' : '#' + marker.color;
          if (mbmarker == '搜索') {
            ctx.strokeStyle =
              marker == state.hoveredMarker
                ? 'rgba(255, 0, 0, 1)'
                : 'rgba(128, 128, 128, 0.5)';
          }

          ctx.lineWidth = 1.5;
          ctx.beginPath();
          ctx.moveTo(markerX, markerY);

          // 确定线条结束点
          const lineEndX = isLeft
            ? Math.max(textX, margin)
            : Math.min(textX, canvas.width - margin);
          ctx.lineTo(lineEndX, textY);
          ctx.stroke();

          // 绘制文本
          ctx.fillStyle =
            marker == state.hoveredMarker ? '#409EFF' : '#' + marker.color;
          if (mbmarker == '搜索') {
            ctx.fillStyle =
              marker == state.hoveredMarker
                ? 'rgba(255, 0, 0, 1)'
                : 'rgba(128, 128, 128, 0.5)';
          }

          ctx.textAlign = isLeft ? 'right' : 'left';
          ctx.font = `${textHeight}px Arial`;
          ctx.fillStyle = 'green';
          if (state.showText) {
            //显示答案
          } else {
            // 必须输入了才显示
            ctx.fillText(index + 1, textX, textY);
            if (marker.userText) {
              ctx.fillText(marker.userText, textX, textY);
            }
          }

          // 更新状态
          state.markers.forEach((item: any) => {
            const itemsArray = item.medicineAtlasImgId.split(',').map(Number);
            if (itemsArray.includes(dcomid.value)) {
              item.bsdata.forEach((markers: any) => {
                if (markers.markingPointsId == marker.markingPointsId) {
                  markers.textX = textX;
                  markers.textY = textY;
                }
              });
            }
          });
        }
      });
    };

    // 绘制左侧和右侧的文本和线条
    drawTextAndLines(leftMarkers.value, true);
    drawTextAndLines(rightMarkers.value, false);

    // 恢复上下文状态
    ctx.restore();
    loding.value = false;
  };
  const saveMarkers = () => {
    // console.log('执行了本地存储',state.markers);
    // localStorage.setItem('markers', JSON.stringify(state.markers));
    // draw("");
  };

  const loadMarkers = () => {
    const cachedMarkers = localStorage.getItem('markers');
    if (cachedMarkers) {
      state.markers = JSON.parse(cachedMarkers);
      draw('');
    }
  };

  const toggleLinesAndText = () => {
    state.showLinesAndText = !state.showLinesAndText;
    draw('');
  };

  // 增加条件开始判断
  const tdflag = ref(false);
  const startDrag = (e: MouseEvent) => {
    // state.isSpacePressed &&
    if (e.button === 0 && tdflag.value == true) {
      state.isDragging = true;
      const rect = state.canvas!.getBoundingClientRect();
      state.startDragX = e.clientX - rect.left - state.imgOffsetX;
      state.startDragY = e.clientY - rect.top - state.imgOffsetY;
      e.preventDefault();
    }
  };

  const stopDrag = () => {
    state.isDragging = false;
    tdflag.value = false;
  };

  const dragMove = (e: MouseEvent) => {
    if (state.isDragging) {
      const rect = state.canvas!.getBoundingClientRect();
      state.imgOffsetX = e.clientX - rect.left - state.startDragX;
      state.imgOffsetY = e.clientY - rect.top - state.startDragY;
      draw('');
    }
  };

  const handleKeyDown = (e: KeyboardEvent) => {
    if (e.code === 'Space') {
      state.isSpacePressed = true;
    }
  };

  const handleKeyUp = (e: KeyboardEvent) => {
    if (e.code === 'Space') {
      state.isSpacePressed = false;
    }
  };

  const tagdcom = (i: number) => {
    flag.value = false;
    // console.log('当前图像id', i);
    const imgsrcd = imgsrc.value.find((item) => item.medicineAtlasImgId == i);

    dcomid.value = i;
    state.img.src = base.value + imgsrcd.imgUrl;
    state.img.onload = () => {
      state.imgWidth = state.img.width;
      state.imgHeight = state.img.height;
    };
    const canvas = state.canvas!;
    const aspectRatio = state.img.naturalWidth / state.img.naturalHeight;
    const canvasAspectRatio = canvas.width / canvas.height;

    // 设置最大宽度和高度
    const maxWidth = canvas.width * 0.999; // 画布宽度的90%
    const maxHeight = canvas.height * 0.999; // 画布高度的90%

    if (canvasAspectRatio > aspectRatio) {
      state.imgScale = Math.min(maxHeight / state.img.naturalHeight, 1);
    } else {
      state.imgScale = Math.min(maxWidth / state.img.naturalWidth, 1);
    }
    draw('');
  };

  const tagdcoms = (i) => {
    const index = imgsrc.value.findIndex(
      (item) => item.medicineAtlasImgId == dcomid.value
    );
    if (i == 1) {
      if (imgsrc.value[index + 1]) {
        dcomid.value = imgsrc.value[index + 1].medicineAtlasImgId;
        tagdcom(dcomid.value);
        draw('');
      }
    } else {
      if (imgsrc.value[index - 1]) {
        dcomid.value = imgsrc.value[index - 1].medicineAtlasImgId;
        tagdcom(dcomid.value);
        draw('');
      }
    }
  };
  const findindex = () => {
    return imgsrc.value.findIndex(
      (item) => item.medicineAtlasImgId == dcomid.value
    );
  };
  const handleWheel = (e: WheelEvent) => {
    e.preventDefault();
    if (e.deltaY < 0 && dcomid.value > 1) {
      const index = imgsrc.value.findIndex(
        (item) => item.medicineAtlasImgId == dcomid.value
      );
      if (imgsrc.value[index - 1]) {
        dcomid.value = imgsrc.value[index - 1].medicineAtlasImgId;
        tagdcom(dcomid.value);
        draw('');
      }
    } else {
      const index = imgsrc.value.findIndex(
        (item) => item.medicineAtlasImgId == dcomid.value
      );
      if (imgsrc.value[index + 1]) {
        dcomid.value = imgsrc.value[index + 1].medicineAtlasImgId;
        tagdcom(dcomid.value);
        draw('');
      }
    }
  };
  const jiegoudata = ref([]);
  const optionsdata = ref([]);

  const boxd = ref();
  // 定义画布高低
  const hbwidth = ref('');
  const hbheight = ref('');

  // 再查询图谱图片

  // cs

  const getTpfn = () => {
    getTp({
      examineId: examineId.value,
    }).then((res) => {
      if (res.code == 200) {
        optionsdata.value = res.data;
        let type = '';
        let imgClassification = '';
        optionsdata.value.forEach((item) => {
          if (item.medicineAtlasId == medicineAtlasId.value) {
            // console.log('查询到相同', item);
            type = item.type;
            imgClassification = item.imgClassificationStr;
          }
        });

        console.log('AAA查询考核图谱成功列表', optionsdata.value);
        // medicineAtlasId.value = res.data[0].medicineAtlasId;
        // 查询考核图片
        getTplist({
          medicineAtlasId: medicineAtlasId.value,
          imgClassification: imgClassification,
          type: type,
        }).then((ress) => {
          if (ress.code == 200) {
            imgsrc.value = ress.data.allImg;
            imgsrcs.value = ress.data.allImg;
            imgclassdata.value = ress.data.classification;
            state.canvas = document.getElementById(
              'myCanvaslxd'
            ) as HTMLCanvasElement;
            console.log('state.canvas', state.canvas);
            state.ctx = state.canvas.getContext('2d');
            console.log('imgsrc', imgsrc.value);

            state.img.src = base.value + imgsrc.value[0].imgUrl;
            dcomid.value = imgsrc.value[0].medicineAtlasImgId;
            state.img.onload = () => {
              // loadMarkers();
              state.imgWidth = state.img.width;
              state.imgHeight = state.img.height;
              draw('');
            };
            state.canvas.addEventListener('mousedown', startDrag);
            state.canvas.addEventListener('mousemove', handleMouseMove);
            state.canvas.addEventListener('mouseup', stopDrag);
            state.canvas.addEventListener('click', handleCanvasClick);
            state.canvas!.addEventListener('touchstart', handleCanvasClick, {
              passive: false,
            });
            state.canvas.addEventListener('touchmove', handleMouseMove);
            state.canvas.addEventListener('wheel', handleWheel);
            // console.log(
            //   '查询考核图片成功',
            //   ress.data,
            //   boxd.value,
            //   imgsrc.value[0].imgUrl
            // );

            // 设置存储图谱的考核题目数据
            const flag = examineRecordDetailsListdata.value.find(
              (item) => item.medicineAtlasId == medicineAtlasId.value
            );
            // console.log('查询是否有新的图谱',flag,medicineAtlasId.value,examineRecordDetailsListdata.value);

            if (!flag) {
              examineRecordDetailsListdata.value.push({
                examineRecordId: examineRecordId.value,
                studentId: studentId.value,
                examineId: examineId.value,
                medicineAtlasId: medicineAtlasId.value,
                examineRecordDetailsList: [],
              });
            } else {
              console.log('已存在考核了');
            }
          }
        });
      }
    });
  };
  getTpfn();
  // cs

  //

  //  查询标记点整合函数
  const getPointfn = () => {
    loding.value = true;
    // 查询标记点为
    getPointnew({
      medicineAtlasId: medicineAtlasId.value,
      pageNum: 1,
      pageSize: 800,
    }).then((res) => {
      if (res.code == 200) {
        state.markers = [];
        saveMarkers();
        console.log('查询解刨点测试', res.data);
        const markersMap = new Map(
          state.markers.map((marker) => [marker.medicineAtlasImgId, marker])
        );

        for (const items of res.data) {
          try {
            if (items.medicineAtlasImgId != null) {
              const existingMarker = markersMap.get(items.medicineAtlasImgId);
              const markingPointsObjects = JSON.parse(items.markingPoints);
              markingPointsObjects.medicineAtlasImgId =
                items.medicineAtlasImgId;

              markingPointsObjects.bsdata[0].markingPointsId =
                items.markingPointsId;
              markingPointsObjects.bsdata[0].flag = true;
              markingPointsObjects.bsdata[0].labels = true;
              markingPointsObjects.bsdata[0].anatomicStructureName =
                items.anatomicStructureName;
              markingPointsObjects.bsdata[0].anatomicStructureId =
                items.anatomicStructureId;

              if (existingMarker) {
                existingMarker.bsdata.push(...markingPointsObjects.bsdata);
              } else {
                markersMap.set(items.medicineAtlasImgId, markingPointsObjects);
              }
            }
          } catch (error) {
            console.error('Error processing item:', items, error);
          }
        }

        // 更新 state.markers
        state.markers = Array.from(markersMap.values());

        // 确保数据不为空
        if (state.markers.length === 0) {
          console.error('Final markers array is empty. Check input data.');
        } else {
          console.log('Final markers:', state.markers);
        }

        // console.log('打印获取的点位数据', state.markers);
        getinputfn();
        draw('');
        loding.value = false;
      }
    });

    // 查询学生信息

    // 获取一下解刨结构数据
    jpList({
      medicineAtlasId: medicineAtlasId.value,
      pageNum: 1,
      pageSize: 999,
    }).then((res) => {
      if (res.code == 200) {
        console.log('查询解刨数据成功', res.data.list);
        optionsdata.value = res.data.list.map((item) => {
          return { ...item, flag: true }; // 为每个对象添加 flag 属性
        });
        // 给结构添加属性来绑定
      }
    });
  };

  const reset = () => {
    // 重置状态
    state.imgScale = 1;
    state.zoomStep = 0.1;
    state.rotation = 0;
    state.flipHorizontal = false;
    state.flipVertical = false;
    state.imgOffsetX = 0;
    state.imgOffsetY = 0;
    state.currentText = '';
    state.currentMarker = null;
    state.addflag = false;
    state.showLinesAndText = true;

    // 重新加载并绘制图像
    const imgsrcd = imgsrc.value.find(
      (item) => item.medicineAtlasImgId == dcomid.value
    );

    state.img.src = base.value + imgsrcd.imgUrl;
    state.img.onload = () => {
      loadMarkers();
      draw('');
    };
  };
  const changecsd = () => {
    if (allflag.value == true) {
      console.log('当前是否全选', allflag.value, state.markers);
      state.markers.forEach((item) => {
        item.bsdata.forEach((items) => {
          items.flag = true;
        });
      });
      // JGkgdata.value.forEach((isd) => {
      //   isd = true;
      //   console.log('sss', isd);
      // });

      JGkgdata.value.forEach((_, index, array) => {
        array[index] = true;
      });
      saveMarkers();
      draw('');
    }
    if (allflag.value == false) {
      state.markers.forEach((item) => {
        item.bsdata.forEach((items) => {
          items.flag = false;
        });
      });

      JGkgdata.value.forEach((_, index, array) => {
        array[index] = false;
      });
      saveMarkers();
      draw('');
    }
  };
  const changecs = (i) => {
    // console.log('关联解剖结构测试', i);
    state.markers.some((item) => {
      const itemsArray = item.medicineAtlasImgId.split(',').map(Number);
      if (itemsArray.includes(dcomid.value)) {
        item.bsdata.some((itemd) => {
          if (itemd.anatomicStructureId == i.anatomicStructureId) {
            itemd.flag = i.flag;
          }
        });
      }
    });
    draw('');
  };

  const JGkgdata = ref([]);
  const allflag = ref(true);
  const classificationName = ref('');
  const imggroupname = ref('');
  const fieldNames = ref({
    value: 'classificationName',
    label: 'classificationName',
  });
  const fieldNamess = ref({
    value: 'typeName',
    label: 'typeName',
  });

  // 图像解刨面更改
  const changeimgclassfn = (i) => {
    console.log('点击了', i);

    // classificationName.value = i.classificationName;
    imgsrc.value = [];
    imgsrcs.value.forEach((item) => {
      if (classificationName.value.includes(item.imgClassificationName)) {
        imgsrc.value.push(item);
      }
    });
    //
    dcomid.value = imgsrc.value[0].medicineAtlasImgId;
    tagdcom(dcomid.value);
  };
  // 图像分组更改
  const changeimggroupfn = (i) => {
    console.log('点击了', i);

    // imggroupname.value = i.typeName;
    const item = imggroup.value.find(
      (img) => img.typeName == imggroupname.value
    );
    // 处理图像classificationName.value.includes(img.imgClassificationName)
    console.log('检测到图像分组更改', item);
    const imgsrcsd = item;
    const imgsrcmw = imgsrc.value;
    imgsrc.value = [];

    //  加一层判断吧
    if (classificationName.value != '') {
      imgsrcsd.typeImg.forEach((itemd) => {
        if (classificationName.value == itemd.imgClassificationName) {
          imgsrc.value.push(itemd);
          console.log('切换图像debug3', imgsrc.value, imgsrc.value.length);
        }
      });
    } else {
      imgsrc.value = imgsrcsd.typeImg;
      console.log('切换图像debug2', imgsrc.value, imgsrc.value.length);
    }

    if (imgsrc.value.length > 0) {
      dcomid.value = imgsrc.value[0].medicineAtlasImgId;
      tagdcom(dcomid.value);
    } else {
      console.log('当前图像没有T2');
      imgsrc.value = imgsrcmw;
      Message.warning({
        content: '暂无图像!',
      });
    }
    // imgsrc.value = item.typeImg;
  };
  const flag = ref(false);
  const flagfn = (i) => {
    // console.log('当前id是否存在本图中', i.anatomicStructureId);
    return state.markers.some((item) => {
      const itemsArray = item.medicineAtlasImgId.split(',').map(Number);
      if (itemsArray.includes(dcomid.value)) {
        return item.bsdata.some(
          (itemd) => itemd.anatomicStructureId === i.anatomicStructureId
        );
      }
      return false;
    });
  };

  // 开始练习
  const startshow = ref(true);

  const visible = ref(false);
  // 提交答案验证
  const handleBeforeOk = (done) => {
    console.log('查询点位验证', state.currentMarker, state.markers);

    state.markers.forEach((item) => {
      const itemsArray = item.medicineAtlasImgId.split(',').map(Number);
      if (itemsArray.includes(dcomid.value)) {
        item.bsdata.forEach((marker) => {
          if (state.currentMarker == marker) {
            marker.userText = formModel.value.userText;
            console.log(
              'state.currentMarker.markingPointsId',
              state.currentMarker.markingPointsId
            );

            // 修改存储答案数组
            const existingItem = examineRecordDetailsList.value.find(
              (itemd) =>
                itemd.markingPointsId == state.currentMarker.markingPointsId
            );

            if (existingItem) {
              existingItem.pointNameInput = formModel.value.userText;
            } else {
              examineRecordDetailsList.value.push({
                medicineAtlasImgId: dcomid.value,
                markingPointsId: state.currentMarker.markingPointsId,
                pointNameInput: formModel.value.userText,
              });
            }

            // 存储到当前考核数组
            examineRecordDetailsListdata.value.forEach((item) => {
              if (item.medicineAtlasId == medicineAtlasId.value) {
                item.examineRecordDetailsList = examineRecordDetailsList.value;
              }
            });

            saveMarkers();
            draw('');
            console.log('存储答案数组成功', examineRecordDetailsList.value);
          }
        });
      }
    });

    visible.value = false;
    done(false);
    formModel.value.userText = '';
  };
  // 填写
  const handleCancel = () => {
    visible.value = false;
    formModel.value.userText = '';
  };
  const formModel = ref({
    userText: '',
  });
  const handleClick = () => {
    visible.value = true;
  };
  onMounted(() => {
    // loding.value = true;
    console.log('boxbox', boxd.value);
    hbheight.value = boxd.value.offsetHeight;
    hbwidth.value = boxd.value.offsetWidth;

    // state.canvas = document.getElementById('myCanvaslxd') as HTMLCanvasElement;
    // console.log('state.canvas', state.canvas);
    // state.ctx = state.canvas.getContext('2d');
    // console.log('imgsrc', imgsrc.value);

    // state.img.src = base.value + imgsrc.value[0].imgUrl;
    // dcomid.value = imgsrc.value[0].medicineAtlasImgId;
    // state.img.onload = () => {
    //   // loadMarkers();
    //   state.imgWidth = state.img.width;
    //   state.imgHeight = state.img.height;
    //   draw("");
    // };
    // state.canvas.addEventListener('mousedown', startDrag);
    // state.canvas.addEventListener('mousemove', handleMouseMove);
    // state.canvas.addEventListener('mouseup', stopDrag);
    // state.canvas.addEventListener('click', handleCanvasClick);
    // state.canvas.addEventListener('wheel', handleWheel);
    document.addEventListener('keydown', handleKeyDown);
    document.addEventListener('keyup', handleKeyUp);

    getPointfn();
  });
  onBeforeUnmount(() => {
    if (state.canvas) {
      state.canvas.removeEventListener('mousedown', startDrag);
      state.canvas.removeEventListener('mousemove', handleMouseMove);
      state.canvas.removeEventListener('mouseup', stopDrag);
      state.canvas.removeEventListener('click', handleCanvasClick);
      state.canvas.removeEventListener('wheel', handleWheel);
    }
    document.removeEventListener('keydown', handleKeyDown);
    document.removeEventListener('keyup', handleKeyUp);
  });
  onUnmounted(() => {
    // 清理临时提交
    stopSaving();
  });
</script>

<style scoped>
  .bjbox {
    width: 100%;
    height: 172px;
  }
  .bjbox img {
    width: 100%;
    height: 172px;
  }
  .mainboxgj {
    display: flex;
    width: 100%;
    height: 100%;
  }
  .mainlefttopbox {
    width: 100%;
    height: 6%;
    background-color: #24292d;
    /* border: 2px solid #5a5a5a; */

    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden;
    position: relative;
  }
  .mainsera {
    position: absolute;
    left: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .maintoptitle {
    font-weight: bold;
    font-size: 20px;
    color: #ffffff;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    justify-content: center;
    align-items: center;
    height: 54px;
  }
  .maintopright {
    display: flex;
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translate(0, -50%);
  }
  .czmainitem {
    cursor: pointer;
    margin: 0 5px;
  }
  .gnbocdtop .arco-btn {
    /* margin: 5px 10px; */
  }
  .gnbocdtop {
    height: 15%;
    background-color: black;
    border-bottom: 2px solid #5a5a5a;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 0px 10px;
  }
  .gnbocd {
    height: 75%;
    overflow: hidden;
    overflow-y: scroll;
    background-color: black;
    border-bottom: 2px solid #5a5a5a;
    display: flex;
    flex-direction: column;
  }
  .gnbocdname {
    font-size: 20px;
    color: #ffffff;
    padding: 10px;
  }
  .gnbottom {
    width: 100%;
    background-color: #24292d;
    height: 10%;

    display: flex;
    align-items: center;
    justify-content: center;
  }
  #myCanvaslxd {
    /* border: solid 1px #00ff80; */
    background-color: black;
  }
  .mentox {
    width: 200px;
    height: 50px;
    background: #121419;
    border-radius: 6px 6px 6px 6px;

    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 500;
    font-size: 18px;
    color: #ffffff;
    margin: 0 13px;
  }
  .mentox span {
    display: block;
    font-weight: bold;
    font-size: 24px;
    margin-left: 10px;
    word-spacing: 20px;
  }
  .boxs {
    width: 300px;
    display: flex;
    flex-direction: column;
    align-content: center;
    justify-content: center;
  }
  .zsdkz {
    font-size: 18px;
    color: #ffffff;
    line-height: 30px;
  }
  .boxsitem {
    width: 130px;
    height: 130px;
    margin: 10px 25px;
    background: black;
  }
  .boxsitems {
    text-align: center;
  }
  .box {
    margin: 0 auto;
    background-color: black;
    width: 100%;
    height: 85%;
  }
  .mainboxleft {
    width: 80%;
    height: 100%;
  }
  .bocd {
    width: 20%;
    height: 100%;
    /* margin: 10px; */
    display: flex;
    flex-direction: column;
    border-left: 2px solid #5a5a5a;
  }

  .lbox {
    width: 100%;
    height: 10%;
    display: flex;
    margin: 0 auto;
    overflow: hidden;
    overflow-x: auto;
    white-space: nowrap;
  }

  .lboxitem {
    background-color: black;
    width: 70px;
    /* height: 70px; */
    cursor: pointer;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .lboxitem img {
    width: 55px;
    height: 55px;
  }

  .msx {
    height: 100px;
    width: 2px;
    background-color: #409eff;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
  .gnbocd::-webkit-scrollbar {
    width: 5px;
    height: 5px;
  }

  .gnbocd::-webkit-scrollbar-track {
    width: 6px;
    background: rgba(#101f1c, 0.1);
    -webkit-border-radius: 2em;
    -moz-border-radius: 2em;
    border-radius: 2em;
  }

  .gnbocd::-webkit-scrollbar-thumb {
    background-color: rgba(133, 138, 148, 0.938);
    background-clip: padding-box;
    min-height: 28px;
    -webkit-border-radius: 2em;
    -moz-border-radius: 2em;
    border-radius: 2em;
    transition: background-color 0.3s;
    cursor: pointer;
  }

  .gnbocd::-webkit-scrollbar-thumb:hover {
    background-color: rgba(144, 147, 153, 0.3);
  }
  .lbox::-webkit-scrollbar {
    width: 5px;
    height: 5px;
  }

  .lbox::-webkit-scrollbar-track {
    width: 6px;
    background: rgba(#101f1c, 0.1);
    -webkit-border-radius: 2em;
    -moz-border-radius: 2em;
    border-radius: 2em;
  }

  .lbox::-webkit-scrollbar-thumb {
    background-color: rgba(133, 138, 148, 0.938);
    background-clip: padding-box;
    min-height: 28px;
    -webkit-border-radius: 2em;
    -moz-border-radius: 2em;
    border-radius: 2em;
    transition: background-color 0.3s;
    cursor: pointer;
  }

  .lbox::-webkit-scrollbar-thumb:hover {
    background-color: rgba(144, 147, 153, 0.3);
  }
  .jgdovx {
    margin: 5px 0;
    display: flex;
    justify-content: space-between;
    width: 100%;
  }
  .xugn {
    display: flex;
    /* justify-content: center;
    align-items: center; */
    margin: 5px 0;

    flex-wrap: wrap;
  }
  .xugname {
    width: 80px;
    color: #fff;
    font-size: 16px;
  }
  .xbanner {
    width: 100%;
    font-size: 16px;
    height: 40px;
    background-color: #fff;
    /* line-height: 40px; */
    padding-left: 10px;
    align-content: center;
  }
  .xbannername {
    cursor: pointer;
    display: flex;
    align-items: center;
    color: #fff;
    font-size: 16px;
  }
  /* 公共类 */
  /* 封装公共按钮类 */
  .tool {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .tool img.active {
    cursor: pointer;
    display: none;
  }

  .tool:hover img.normal,
  .tool.active img.normal {
    display: none;
  }

  .tool:hover img.active,
  .tool.active img.active {
    display: block;
  }
  .gnboxmain {
    padding: 0 15px;
  }
  .gnboxitem {
    height: 40px;
    background: #24292d;
    border-radius: 4px 4px 4px 4px;
    display: flex;
    align-items: center;
    color: #fff;
    padding: 0 12px;
    margin: 10px 0;
    font-size: 16px;
  }
  .zsbox {
    width: 384px;
    height: 910px;
    background-color: #121419;
    display: flex;
    flex-direction: column;
    position: fixed;
    top: 0px;
    right: 0px;
    z-index: 9;
  }
  .zstop {
    height: 54px;
    width: 100%;
    font-size: 16px;
    color: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    border-bottom: 2px solid #363739;
  }
  .startbox {
    width: 90px;
    height: 37px;
    background: linear-gradient(180deg, #f4f4f4 0%, #a2a2a2 100%);
    border-radius: 4px 4px 4px 4px;
    border: 1px solid #000000;
    font-weight: bold;
    font-size: 16px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 5px;
  }
  .zsclose {
    position: absolute;
    right: 20px;
    cursor: pointer;
  }
  .startbox:hover {
    color: #007dff;
  }
  .startboxs {
    color: #fff;
    margin-left: 10px;
  }
  .jpan {
    background-color: #424548;
    border-radius: 4px;
    /* padding: 10px 28px; */
    cursor: pointer;
    width: 108px;
    height: 38px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 5px 7px;
    text-align: center;
  }
  .jpanitem {
    width: 70%;
    color: #fff;
    text-wrap: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .jpan:hover {
    background-color: #409eff;
    border-radius: 4px;
    max-width: 108px;
  }
  .jpanac {
    background-color: #409eff;
    border-radius: 4px;
    max-width: 108px;
  }
  .timerbox {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8px 15px;
    background: #424548;
    border-radius: 4px 4px 4px 4px;
    border: 1px solid #000000;
    color: #a0a2a3;
    font-size: 18px;
    margin-left: 10px;
  }
  .tcbox {
    width: 713px;
    height: 429px;
    background: #ffffff;
    border-radius: 0px 0px 0px 0px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 999;
    display: flex;
    flex-direction: column;
  }
  .tctopbox {
    width: 100%;
    height: 46px;
    background: #cfcfcf;
    display: flex;
    align-items: center;
  }
  .tcclose {
    position: absolute;
    right: 10px;
    cursor: pointer;
  }
  .tctopname {
    font-size: 16px;
    color: #000000;
    margin: 0 auto;
  }
  .tcmainbox {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 40px 0;
  }
  .tcmainitem {
    display: flex;
    align-items: center;
    margin: 0 auto;
    border: 1px solid #c1c1c1;
    width: 491px;
    height: 44px;
  }
  .tcitemname {
    width: 175px;
    height: 44px;
    font-size: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-right: 1px solid #c1c1c1;
  }
  .tcitdes {
    width: 100%;
    height: 100%;
    font-size: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .zzcbox {
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.6);
    z-index: 99;
    position: absolute;
    top: 0;
    left: 0;
  }
  .startboxss {
    width: 112px;
    height: 37px;
    background: linear-gradient(180deg, #ffffff 0%, #c0c0c0 100%);
    border-radius: 4px 4px 4px 4px;
    border: 1px solid #999999;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto;
    cursor: pointer;
    font-size: 16px;
  }
  .tsred {
    color: red;

    position: absolute;
    bottom: 95px;
    left: 50%;
    transform: translate(-50%, 0);
  }
</style>
